import React, { ReactElement } from 'react';
import { render, RenderOptions } from '@testing-library/react';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { vi, expect } from 'vitest';
import { BrowserRouter } from 'react-router-dom';
import { ConfigProvider } from 'antd';
import zhCN from 'antd/locale/zh_CN';
import type { 
  SearchResult, 
  SearchSuggestion, 
  User, 
  RecommendationResult,
  ContentType 
} from '@/types';

// 创建测试用的 QueryClient
const createTestQueryClient = () => new QueryClient({
  defaultOptions: {
    queries: {
      retry: false,
      gcTime: 0,
    },
    mutations: {
      retry: false,
    },
  },
});

// 测试包装器组件
const TestProviders: React.FC<{ children: React.ReactNode }> = ({ children }) => {
  const queryClient = createTestQueryClient();
  
  return (
    <QueryClientProvider client={queryClient}>
      <ConfigProvider locale={zhCN}>
        <BrowserRouter>
          {children}
        </BrowserRouter>
      </ConfigProvider>
    </QueryClientProvider>
  );
};

// 自定义渲染函数
const customRender = (
  ui: ReactElement,
  options?: Omit<RenderOptions, 'wrapper'>
) => render(ui, { wrapper: TestProviders, ...options });

// 重新导出所有 testing-library 工具
export * from '@testing-library/react';
export { customRender as render };

// 测试数据生成器
export const createMockSearchResult = (overrides?: Partial<SearchResult>): SearchResult => ({
  id: 'test-result-1',
  title: '测试搜索结果',
  description: '这是一个测试用的搜索结果描述',
  url: 'https://example.com/test',
  publishDate: new Date('2024-01-01'),
  source: 'example.com',
  contentType: 'web' as ContentType,
  relevanceScore: 0.95,
  popularity: 1000,
  rating: 4.5,
  language: 'zh-CN',
  tags: ['测试', '示例'],
  highlights: {
    title: ['测试'],
    description: ['测试用的'],
  },
  ...overrides,
});

export const createMockSearchSuggestion = (overrides?: Partial<SearchSuggestion>): SearchSuggestion => ({
  id: 'test-suggestion-1',
  text: '测试建议',
  type: 'suggestion',
  frequency: 100,
  category: '测试',
  metadata: {
    popularity: 80,
    resultCount: 1000,
  },
  ...overrides,
});

export const createMockUser = (overrides?: Partial<User>): User => ({
  id: 'test-user-1',
  username: 'testuser',
  email: 'test@example.com',
  displayName: '测试用户',
  avatar: 'https://example.com/avatar.jpg',
  location: {
    country: '中国',
    region: '北京',
    city: '北京',
  },
  createdAt: Date.now() - 86400000, // 1天前
  lastLoginAt: Date.now() - 3600000, // 1小时前
  isActive: true,
  role: 'user',
  ...overrides,
});

export const createMockRecommendation = (overrides?: Partial<RecommendationResult>): RecommendationResult => ({
  id: 'test-recommendation-1',
  type: 'personalized',
  title: '测试推荐内容',
  description: '这是一个测试用的推荐内容描述',
  url: 'https://example.com/recommendation',
  contentType: 'web' as ContentType,
  score: 0.9,
  confidence: 0.85,
  reason: '基于您的搜索历史推荐',
  tags: ['推荐', '测试'],
  createdAt: Date.now() - 1800000, // 30分钟前
  ...overrides,
});

// 测试用的 Mock 函数
export const mockFetch = (data: any, ok = true, status = 200) => {
  return vi.fn().mockResolvedValue({
    ok,
    status,
    json: () => Promise.resolve(data),
    text: () => Promise.resolve(JSON.stringify(data)),
  });
};

// 等待异步操作完成
export const waitForAsync = () => new Promise(resolve => setTimeout(resolve, 0));

// 模拟用户交互
export const mockUserEvent = {
  click: (element: Element) => {
    element.dispatchEvent(new MouseEvent('click', { bubbles: true }));
  },
  type: (element: HTMLInputElement, text: string) => {
    element.value = text;
    element.dispatchEvent(new Event('input', { bubbles: true }));
    element.dispatchEvent(new Event('change', { bubbles: true }));
  },
  keyDown: (element: Element, key: string) => {
    element.dispatchEvent(new KeyboardEvent('keydown', { key, bubbles: true }));
  },
  focus: (element: HTMLElement) => {
    element.focus();
    element.dispatchEvent(new FocusEvent('focus', { bubbles: true }));
  },
  blur: (element: HTMLElement) => {
    element.blur();
    element.dispatchEvent(new FocusEvent('blur', { bubbles: true }));
  },
};

// 测试断言辅助函数
export const expectElementToBeVisible = (element: Element | null) => {
  expect(element).toBeInTheDocument();
  expect(element).toBeVisible();
};

export const expectElementToHaveText = (element: Element | null, text: string) => {
  expect(element).toBeInTheDocument();
  expect(element).toHaveTextContent(text);
};

export const expectElementToHaveClass = (element: Element | null, className: string) => {
  expect(element).toBeInTheDocument();
  expect(element).toHaveClass(className);
};

// 测试环境检查
export const isTestEnvironment = () => import.meta.env.MODE === 'test';

// 模拟延迟
export const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));

// 创建测试用的错误对象
export const createTestError = (message = '测试错误', code = 'TEST_ERROR') => ({
  message,
  code,
  timestamp: Date.now(),
});

// 模拟 API 响应
export const createMockAPIResponse = <T,>(data: T, success = true) => ({
  success,
  data,
  message: success ? '操作成功' : '操作失败',
  timestamp: Date.now(),
});

// 模拟分页响应
export const createMockPaginatedResponse = <T,>(
  data: T[],
  page = 1,
  pageSize = 20,
  total = data.length
) => ({
  success: true,
  data,
  pagination: {
    page,
    pageSize,
    total,
    totalPages: Math.ceil(total / pageSize),
    hasNext: page * pageSize < total,
    hasPrev: page > 1,
  },
  timestamp: Date.now(),
});
